package chen.web.forum;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;

import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.util.Assert;

import chen.web.DataSourceProvider;
import chen.web.MyContextProvider;
import chen.web.user.Account;
import chen.web.util.DateInt;
import chen.web.widget.Widget;
import chen.web.widget.WidgetManagerFactory;

class SubjectManager {
	private static SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(DataSourceProvider.getDataSource());
	private static JdbcTemplate  jdbcTemplate  = new JdbcTemplate(DataSourceProvider.getDataSource());
	
	private ForumAccountLoader fal = null;
	private CategoryManager cm = null;
	private WidgetManagerFactory wmf = null;
	SubjectManager(ForumAccountLoader fal, CategoryManager cm, WidgetManagerFactory wmf){
		this.fal = fal;
		this.cm = cm;
		this.wmf = wmf;
	}
	
	private static final String SQL_25 = "select * from web_subject where sub_id = ?";

	public Subject getSubject(int subjectId) {
		// TODO Auto-generated method stub
		Subject subject = null;
		try{
			subject = simpleJdbcTemplate.queryForObject(SQL_25, new SubjectRowMapper(), subjectId);
		} catch(EmptyResultDataAccessException e){
			return null;
		}
		
		int authorId = subject.getAuthor().getId();
		ForumAccount author = fal.loadForumAccount(authorId);
		subject.setAuthor(author);
		Category category = subject.getCategory();
		category = cm.get(category.getId());
		subject.setCategory(category);
		
		Widget widget = subject.getWidget();
		if(widget != null){
			subject.setWidget(wmf.getWidgetManager(widget.getClass()).get(widget.getId()));
		}
		return subject;
	}
	
	private static final String SQL_23 = "update web_subject set sub_viewCount = sub_viewCount + 1 where sub_id = ?";
	public void increaseViewCount(Subject subject) {
		// TODO Auto-generated method stub
		simpleJdbcTemplate.update(SQL_23, subject.getId());
	}
	
	private static final String SQL_10 = "insert into web_subject(sub_title, sub_content, sub_authorId, sub_authorNickname, sub_lastReplyDate, sub_lastReplierId, sub_lastReplierNickname, sub_dateline, sub_ip, sub_flag, sub_widgetType, sub_widgetId, sub_invisible, cat_id) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
	public Subject post(final Subject subject) throws NotLowestException {
		// TODO Auto-generated method stub
		if(subject.getCategory().getChildren().size() > 0){
			throw new NotLowestException();
		}
		subject.setAuthor(fal.loadForumAccount(MyContextProvider.getMyContext().getAccount()));
		final String title = subject.getTitle();
		final String content = subject.getContent();
		subject.setIp(MyContextProvider.getMyContext().getIp());
		subject.setDateline(new Date());
		subject.setNeedChecking(subject.getCategory().isCheckSubject());
		if(title == null || content == null || title.trim().length() == 0){
			throw new IllegalArgumentException();
		}
		
		Widget widget = subject.getWidget();
		if(widget != null){
			widget = wmf.getWidgetManager(widget.getClass()).add(widget);
			subject.setWidget(widget);
		}
		
		KeyHolder keyHolder = new GeneratedKeyHolder();
		jdbcTemplate.update(new PreparedStatementCreator(){
			@Override
			public PreparedStatement createPreparedStatement(Connection conn)
					throws SQLException {
				// TODO Auto-generated method stub
				PreparedStatement ps = conn.prepareStatement(SQL_10, PreparedStatement.RETURN_GENERATED_KEYS);
				ps.setString(1, title);
				ps.setString(2, content);
				ForumAccount author = subject.getAuthor();
				ps.setInt(3, author.getId());
				ps.setString(4, author.getAccount().getNickname());	
				ps.setInt(5, DateInt.transform(new Date())); 
				ps.setInt(6, author.getId());
				ps.setString(7, author.getAccount().getNickname());	
				ps.setInt(8, DateInt.transform(subject.getDateline()));
				ps.setString(9, subject.getIp()); 
				ps.setInt(10, subject.getFlag()); 
				Widget widget = subject.getWidget();
				if(widget == null){
					ps.setInt(11, 0);
					ps.setInt(12, 0);
				}else{
					ps.setInt(11, WidgetType.getType(widget.getClass()));
					ps.setInt(12, widget.getId());
				}
				int invisible = 0;
				if(subject.isFakeDelete())	invisible = 1;
				if(subject.isNeedChecking()) invisible = 2;
				ps.setInt(13, invisible);
				ps.setInt(14, subject.getCategory().getId());
				return ps;
			}
		
		}, keyHolder);
		
		int id = keyHolder.getKey().intValue();
		subject.setId(id);
		return subject;
	}
	
	static final class SubjectRowMapper implements RowMapper<Subject>{

		@Override
		public Subject mapRow(ResultSet rs, int rowNum) throws SQLException {
			// TODO Auto-generated method stub
			Subject subject = new Subject();
			subject.setContent(rs.getString("sub_content"));
			subject.setDateline(DateInt.transform(rs.getInt("sub_dateline")));
			subject.setFlag(rs.getInt("sub_flag"));
			subject.setId(rs.getInt("sub_id"));
			subject.setTitle(rs.getString("sub_title"));
			subject.setViewCount((rs.getInt("sub_viewCount")));
			subject.setDigest(rs.getBoolean("sub_good"));
			subject.setTop(rs.getBoolean("sub_top"));
			subject.setIp(rs.getString("sub_ip"));
			subject.setReplyCount(rs.getInt("sub_replyCount"));
			
			int invisible = rs.getInt("sub_invisible");
			if(invisible==1){
				subject.setFakeDelete(true);
			}
			if(invisible==2){
				subject.setNeedChecking(true);
			}
			
			int authorId = rs.getInt("sub_authorId");
			Account author = new Account(authorId);
			subject.setAuthor(new ForumAccount(author));
			int widgetType = rs.getInt("sub_widgetType");
			int widgetId = rs.getInt("sub_widgetId");
			Widget widget = null;
			if(widgetType != 0){
				widget = WidgetType.createWidget(widgetType, widgetId);
			}
			subject.setWidget(widget);
			int categoryId = rs.getInt("cat_id");
			Category category = new Category(categoryId);
			subject.setCategory(category);
			return subject;
		}
	}
	
	public int totalSubject(SubjectCondition condition) {
		// TODO Auto-generated method stub
		StringBuffer sql = new StringBuffer();
		sql.append("select count(*) from web_subject")
			.append(condition.toSql());
		int amount = simpleJdbcTemplate.queryForInt(sql.toString());
		return amount;
	}
	
	private static final String SQL_3 = "delete from web_subject where sub_id = ?";
	public void delete(Subject subject) {
		// TODO Auto-generated method stub
		simpleJdbcTemplate.update(SQL_3, subject.getId());
	}
	
	private static final String SQL_18 = "update web_subject set sub_title= ?, sub_content = ?, sub_top = ?, sub_good = ?, sub_flag = ?, cat_id = ?, sub_invisible = ? where sub_id = ?";
	public void update(Subject subject){
		final String title = subject.getTitle();
		final String content = subject.getContent();
		Assert.hasLength(subject.getTitle());
		Assert.hasLength(subject.getContent());
		Assert.notNull(subject.getCategory());
		Assert.isTrue(subject.getId() > 0);
		int invisiable = subject.isFakeDelete()?1 :subject.isNeedChecking()?2:0;
		simpleJdbcTemplate.update(SQL_18, title, content, subject.isTop(), subject.isDigest(), subject.getFlag(), subject.getCategory().getId(), invisiable, subject.getId());
	}
	
	
}
